package com.service.business.order.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.service.business.base.dto.LoginUserSession;
import com.service.business.base.service.CoinService;
import com.service.business.base.service.ConfigService;
import com.service.business.fil.service.SysQuotesIpfxService;
import com.service.business.member.controller.rep.MemberJARep;
import com.service.business.member.dto.MemberStoreChange;
import com.service.business.member.service.*;
import com.service.business.order.controller.rep.*;
import com.service.business.order.controller.req.OrderComboPageReq;
import com.service.business.order.controller.req.OrderReq;
import com.service.business.order.controller.req.RenewOrderReq;
import com.service.business.order.dto.IPFSConstant;
import com.service.business.order.service.OrderProductHrComboDetailsService;
import com.service.business.order.service.OrderProductHrComboPaddingService;
import com.service.business.order.service.OrderProductHrComboService;
import com.service.business.order.service.RankMiningPoolRecordService;
import com.service.business.order.utils.OrderUtils;
import com.service.business.pay.service.PayService;
import com.service.business.product.controller.rep.ProductPayTypeRep;
import com.service.business.product.service.ProductHrComboService;
import com.service.business.product.service.ProductPayTypeService;
import com.service.business.support.*;
import com.service.business.utils.DateUtil;
import com.service.business.utils.I18nUtil;
import com.service.core.exception.CommonException;
import com.service.core.rest.response.CommonPageRep;
import com.service.dao.constants.ConfigConstants;
import com.service.dao.dto.MemberRank;
import com.service.dao.dto.OrderMemberRank;
import com.service.dao.dto.rep.OrderProductHrComboRep;
import com.service.dao.enums.*;
import com.service.dao.mapper.MemberGradeConfigMapper;
import com.service.dao.mapper.MemberMapper;
import com.service.dao.mapper.OrderProductHrComboMapper;
import com.service.dao.mapper.ProductHrComboMapper;
import com.service.dao.model.*;
import com.service.utility.common.MathUtil;
import com.service.utility.common.UUIDUtil;
import com.service.utility.modelmapper.ModelMapperUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;


/**
 * @author lisi
 */
@Slf4j
@Service("hashRateOrderService")
@SuppressWarnings("all")
public class OrderProductHrComboServiceImpl extends ServiceImpl<OrderProductHrComboMapper, OrderProductHrCombo> implements OrderProductHrComboService {

	@Autowired
	private OrderUtils orderUtils;
	@Autowired
	private ShoppingCar shoppingCar;
	@Autowired
	private SessionUtil sessionUtil;
	@Autowired
	private MemberMapper memberMapper;
	@Autowired
	private MemberService memberService;
	@Autowired
	private ProductHrComboMapper productHrComboMapper;
	@Autowired
	private MemberGradeConfigMapper memberGradeConfigMapper;
	@Autowired
	private MemberStoreService memberStoreService;
	@Autowired
	private MemberStoreLockUtils memberStoreLockUtils;
	@Autowired
	private PayService payService;
	@Autowired
	private ConfigService configService;
	@Autowired
	private CoinService coinService;
	@Autowired
	private MemberJAService memberJAService;
	@Autowired
	private ProductHrComboService productHrComboService;
	@Autowired
	private ProductPayTypeService productPayTypeService;
	@Autowired
	private OrderProductHrComboDetailsService orderDetailsService;
	@Autowired
	private MemberMiningOrderService miningOrderService;
	@Autowired
	private MemCacheNoTran memCache;
	@Autowired
	private SysQuotesIpfxService sysQuotesIpfxService;
	@Autowired
	private MemberCacheService memberCacheService;
	@Autowired
	private RankMiningPoolRecordService rankMiningPoolRecordService;
	@Autowired
	private OrderProductHrComboPaddingService orderProductHrComboPaddingService;

	@Value("${productHrComboOrderPrefix}")
	private String productOtherOrderPrefix;

	@Override
	@Transactional(rollbackFor = Exception.class)
	public BaseOrderRep orderHashRateCombo(OrderReq orderReq) {

		LoginUserSession session = sessionUtil.getUser();
		if (session.getStoreFreezeStatus() == com.service.dao.enums.MemberEnums.StoreStatus.FROZEN.getCode()) {
			throw new CommonException("账户资产已冻结，如有疑问请联系客服", "account_assets_frozen");
		}
		ProductHrCombo combo = productHrComboMapper.selectById(orderReq.getId());
		if (ObjectUtils.isEmpty(combo) || !ObjectUtils.nullSafeEquals(combo.getComboStatus(), CommonStatusEnums.ACTIVE.getCode())) {
			throw new CommonException("不存在此套餐", "hash_rate_combo_not_exist");
		}

		if (combo.getMinBuyNum() > orderReq.getNum()) {
			throw new CommonException("购买数量少于起购数量", "order_num_less_then");
		}

//        BigDecimal totalHashRate = baseMapper.getTotalOrderNumByOrderStatus(HashRateOrderEnums.getHrComboUsingStatus(), session.getUserId());

//        Member member = memberMapper.selectById(session.getUserId());
//        MemberGradeConfig memberGradeConfig = memberGradeConfigMapper.selectById(member.getVipGrade());
//        BigDecimal total = totalHashRate.add(MathUtil.mul(combo.getComputingPower(), orderReq.getNum()));
//        if (total.compareTo(memberGradeConfig.getTotalHrComboRunning()) >= 0) {
//            throw new CommonException("超出该会员等级累计最大在挖算力", "member_grade_beyond_total_running");
//        }

		if (!ObjectUtils.nullSafeEquals(combo.getComboStatus(), CommonStatusEnums.ACTIVE.getCode())) {
			shoppingCar.removeHashRateComboFromCar(session.getUserId());
			throw new CommonException("算力套餐已下架，请重新选购套餐", "hash_rate_combo_sold_out");
		}

		if (combo.getStock() >= 0 && orderReq.getNum() > combo.getStock()) {
			//TODO:是否给管理员发送告警
			throw new CommonException("算力套餐库存不足", "hash_rate_combo_stock_is_deficiency");
		}
		if (!ObjectUtils.isEmpty(combo.getLimitBuyNum()) && combo.getLimitBuyNum() > 0 && orderReq.getNum() > combo.getLimitBuyNum()) {
			throw new CommonException(I18nUtil.getMessage("out_of_limit_buy", Language.LANG.get(), combo.getLimitBuyNum()));
		}
		BigDecimal orderMoney = combo.getComboPrice().multiply(new BigDecimal(orderReq.getNum()));
		List<ProductPayTypeRep> productPayTypeList = productPayTypeService.listValidPayTypeByOrderType(orderMoney, sessionUtil.getUser().getUserId(), combo.getComboType());
		if (ObjectUtils.isEmpty(productPayTypeList)) {
			throw new CommonException("会员余额不足", "store_balance_not_enough");
		}
		//判断当前用户是否有该产品的未支付订单
		Integer notPayOrderNum = baseMapper.totalNotPayOrderByMemberIdAndComboId(session.getUserId(), combo.getId());
		if (notPayOrderNum > 0) {
			throw new CommonException("您已有该套餐的未支付订单，请先支付", "already_have_not_pay_order");
		}
		Date currentDate = new Date();
		OrderProductHrCombo orderProductHrCombo = new OrderProductHrCombo();
		orderProductHrCombo.setOrderType(combo.getComboType());
		orderProductHrCombo.setHrOrderNo(buildShopOrderNo());
		orderProductHrCombo.setMemberId(session.getUserId());
		orderProductHrCombo.setMemberAccount(session.getAccount());
		orderProductHrCombo.setTotalComboNum(orderReq.getNum());
		orderProductHrCombo.setTotalHashRate(MathUtil.mul(combo.getComputingPower(), orderReq.getNum()));
		orderProductHrCombo.setOrderMoney(orderMoney);
		orderProductHrCombo.setOrderStatus(HashRateOrderEnums.Status.not_pay.getCode());
		orderProductHrCombo.setCreateTime(currentDate);
		orderProductHrCombo.setCustodyFee(combo.getCustodyFee());
		orderProductHrCombo.setOrderSource(HashRateOrderEnums.Source.RATE_MALL.getSourceCode());
		orderProductHrCombo.setStartTime(DateUtils.addDays(new Date(), combo.getPackageDays()));
		orderProductHrCombo.setEndTime(DateUtils.addDays(orderProductHrCombo.getStartTime(), combo.getDeadline()));
		baseMapper.insert(orderProductHrCombo);
		orderDetailsService.createOrderDetail(combo, orderReq.getNum(), orderProductHrCombo);
		productHrComboService.updateProductStockNum(combo.getId(), orderReq.getNum());
		return BaseOrderRep.buildProductHrCombo(orderProductHrCombo, orderUtils.getOvertime(currentDate));
	}

	@Override
	public String buildShopOrderNo() {
		String no = productOtherOrderPrefix + DateFormatUtils.format(new Date(), "yyyyMMdd") + UUIDUtil.randomUUID10().substring(0, 8);
		OrderProductHrCombo orderList = getOne(new QueryWrapper<OrderProductHrCombo>().lambda()
				.eq(OrderProductHrCombo::getHrOrderNo, no).last(" limit 1"));
		if (!ObjectUtils.isEmpty(orderList)) {
			no = buildShopOrderNo();
		}
		return no;
	}

	@Override
	public CommonPageRep<OrderHrComboPageRep> page(OrderComboPageReq pageReq) {

		Page<OrderProductHrComboRep> page = PageHelper.startPage(pageReq.getPageNo(), pageReq.getPageSize());
		List<OrderProductHrComboRep> combos = baseMapper.pageByCoins1(pageReq.getOrderStatus(), sessionUtil.getUser().getUserId(), pageReq.getCoins().getCode(),pageReq.getType());
//		list(new QueryWrapper<OrderProductHrCombo>().lambda()
//				.eq(OrderProductHrCombo::getOrderStatus, pageReq.getOrderStatus())
//				.eq(OrderProductHrCombo::getMemberId, sessionUtil.getUser().getUserId())
//				.orderByDesc(OrderProductHrCombo::getCreateTime));

		Map<String, SysConfig> configMap = configService.getConfigMapByGroup(ConfigConstants.Group.mall.getCode());
		SysConfig config = configMap.get(ConfigConstants.ORDER_OVERDUE_TIME);

		List<OrderHrComboPageRep> pageRepList = combos.stream().map(item -> {
			OrderHrComboPageRep pageRep = ModelMapperUtil.getStrictModelMapper().map(item, OrderHrComboPageRep.class);
			List<ProductPayTypeRep> list = productPayTypeService.listByOrderType(item.getOrderType());
			pageRep.setOrderMoneyCoin(list.get(0).getPayName());
			if (ObjectUtils.nullSafeEquals(pageReq.getOrderStatus(), HashRateOrderEnums.Status.not_pay.getCode())) {
				pageRep.setValidTime(DateUtil.getValidTime(item.getCreateTime(), Integer.parseInt(config.getConfValue())));
			}
			OrderProductHrComboDetails details = orderDetailsService.getOne(new QueryWrapper<OrderProductHrComboDetails>().lambda()
					.eq(OrderProductHrComboDetails::getHrOrderId, item.getId()));
			//统计释放冻结
			BigDecimal forestReleaseNum = miningOrderService.totalMiningFrostNum(item.getMemberId(), details.getCoinsId(), item.getId(), null);
			pageRep.setForestReleaseNum(forestReleaseNum);
			pageRep.setPledgeNum(details.getPledgeNum());
			pageRep.setGasNum(details.getGasNum());
			pageRep.setUsdtNum(details.getUsdtNum());
			pageRep.setRenewalDays(details.getRenewalDays());
			SysConfig limitRenewConfig = configService.getConfigByName(ConfigConstants.ORDER_RENEW_LIMIT_DAYS);
			int nextNum = 0;
			if (!ObjectUtils.isEmpty(limitRenewConfig) && StringUtils.isNotEmpty(limitRenewConfig.getConfValue())) {
				nextNum = Integer.parseInt(limitRenewConfig.getConfValue());
			}
			if (ObjectUtils.isEmpty(item.getEndTime())) {
				pageRep.setCanRenewStatus(CommonStatusEnums.INVALID.getCode());
			} else {
				//判断是否满足续约条件
				Date limitDate = DateUtil.nextCurrentDays(item.getEndTime(), nextNum);
				Date current = new Date();
				if (item.getOrderStatus() == OrderProductOtherStatus.COMPLETED.getCode() && current.before(limitDate)) {
					pageRep.setCanRenewStatus(CommonStatusEnums.ACTIVE.getCode());
				} else if (item.getOrderStatus() == OrderProductOtherStatus.COMPLETED.getCode() && current.after(limitDate)) {
					pageRep.setCanRenewStatus(CommonStatusEnums.INVALID.getCode());
				} else {
					pageRep.setCanRenewStatus(CommonStatusEnums.INVALID.getCode());
				}
			}
			return pageRep;
		}).collect(Collectors.toList());
		Collections.sort(pageRepList, new Comparator<OrderHrComboPageRep>() {
			@Override
			public int compare(OrderHrComboPageRep n1, OrderHrComboPageRep n2) {
				try {
					long dt1 = n1.getCreateTime().getTime();
					long dt2 = n2.getCreateTime().getTime();
					if (dt1 > dt2) {
						return -1;
					} else if (dt1 < dt2) {
						return 1;
					} else {
						return 0;
					}
				} catch (Exception e) {
					e.printStackTrace();
				}
				return 0;
			}
		});
		return CommonPageRep.buildResultRep(page, pageRepList);
	}

	@Override
	public OrderHrComboDetailRep getOrderDetail(String orderNo) {
		OrderProductHrCombo productHrCombo = getOrderDetailByOrderNo(orderNo);
		OrderHrComboDetailRep detailRep = ModelMapperUtil.map(productHrCombo, OrderHrComboDetailRep.class);
		List<ProductPayTypeRep> list = productPayTypeService.listByOrderType(productHrCombo.getOrderType());
		detailRep.setOrderMoneyCoin(list.get(0).getPayName());
		detailRep.setRenewTime(orderDetailsService.getOne(new QueryWrapper<OrderProductHrComboDetails>().lambda()
				.eq(OrderProductHrComboDetails::getHrOrderId, productHrCombo.getId())).getRenewTime());
		detailRep.setMiningCoin(orderDetailsService.list(new QueryWrapper<OrderProductHrComboDetails>().lambda()
				.eq(OrderProductHrComboDetails::getHrOrderId, productHrCombo.getId())).get(0).getCoinsName());

		if (ObjectUtils.nullSafeEquals(productHrCombo.getOrderStatus(), HashRateOrderEnums.Status.not_pay.getCode())) {
			SysConfig config = configService.getConfigByName(ConfigConstants.ORDER_OVERDUE_TIME);
			if (!ObjectUtils.isEmpty(config) && StringUtils.isNotBlank(config.getConfValue())) {
				detailRep.setValidTime(DateUtil.getValidTime(detailRep.getCreateTime(), Integer.parseInt(config.getConfValue())));
			}
		}

		if (!ObjectUtils.nullSafeEquals(productHrCombo.getOrderStatus(), HashRateOrderEnums.Status.not_pay.getCode())
				&& !ObjectUtils.nullSafeEquals(productHrCombo.getOrderStatus(), HashRateOrderEnums.Status.noneffective.getCode())) {
			detailRep.setPayRecordList(payService.getProductHrComboPayRecord(productHrCombo.getId(), productHrCombo.getPayTypeGroup(), productHrCombo.getOrderType()));
		}

		if (ObjectUtils.nullSafeEquals(productHrCombo.getOrderStatus(), HashRateOrderEnums.Status.payed_effective.getCode())
				|| ObjectUtils.nullSafeEquals(productHrCombo.getOrderStatus(), HashRateOrderEnums.Status.complete.getCode())) {
			detailRep.setMiningRecords(memberJAService.getMiningRecord(productHrCombo.getMemberId(), productHrCombo.getId()));
		}

		return detailRep;
	}

	/**
	 * @Description: 统计当前订单的收益明细
	 * @Author: ty
	 * @Date: 2021/4/29 11:35
	 * @param: [orderNo]
	 * @return: com.service.business.order.controller.rep.OrderRewardDetailsRep
	 **/
	@Override
	public OrderRewardDetailsRep getOrderRewardDetail(Integer orderId) {
		OrderProductHrCombo productHrCombo = getById(orderId);
		OrderProductHrComboDetails details = orderDetailsService.getOne(new QueryWrapper<OrderProductHrComboDetails>().lambda()
				.eq(OrderProductHrComboDetails::getHrOrderId, productHrCombo.getId()));
		OrderHrComboDetailRep detailRep = ModelMapperUtil.map(productHrCombo, OrderHrComboDetailRep.class);
		OrderRewardDetailsRep rep = new OrderRewardDetailsRep();
		List<JournalAccount> journalAccounts = memberJAService.list(new QueryWrapper<JournalAccount>().lambda()
				.eq(JournalAccount::getOrderId, orderId)
				.eq(JournalAccount::getJaId, MemberJAType.MINING.getCode())
				.eq(JournalAccount::getMemberId, sessionUtil.getUser().getUserId())
				.orderByDesc(JournalAccount::getCreateTime)
		);
		if (ObjectUtils.isEmpty(journalAccounts)) {
			rep.setJaList(new ArrayList<>());
		}
		List<MemberJARep> jaReps = new ArrayList<>();
		for (JournalAccount ja : journalAccounts) {
			MemberJARep jaRep = ModelMapperUtil.getStrictModelMapper().map(ja, MemberJARep.class);
			jaReps.add(jaRep);
		}
		rep.setJaList(jaReps);
		Date current = new Date();
		//累计冻结
		BigDecimal totalFrostNum = miningOrderService.totalMiningFrostNum(sessionUtil.getUser().getUserId(), details.getCoinsId(), orderId, null);
		//累计释放
		BigDecimal totalReleaseNum = miningOrderService.totalMiningReleaseNum(sessionUtil.getUser().getUserId(), details.getCoinsId(), orderId, null);
		//今日冻结
		BigDecimal todayFrostNum = miningOrderService.totalMiningFrostNum(sessionUtil.getUser().getUserId(), details.getCoinsId(), orderId, current);
		//今日释放
		BigDecimal todayReleaseNum = miningOrderService.totalMiningReleaseNum(sessionUtil.getUser().getUserId(), details.getCoinsId(), orderId, current);
		rep.setTotalFrostNum(totalFrostNum);
		rep.setTotalReleaseNum(totalReleaseNum);
		rep.setTodayFrostNum(todayFrostNum);
		rep.setTodayReleaseNum(todayReleaseNum);
		return rep;
	}

	@Override
	public OrderProductHrCombo getOrderDetailByOrderNo(String orderNo) {
		final OrderProductHrCombo productHrCombo = getOne(new QueryWrapper<OrderProductHrCombo>().lambda().eq(OrderProductHrCombo::getHrOrderNo, orderNo));
		if (ObjectUtils.isEmpty(productHrCombo)) {
			throw new CommonException("不存在此订单", "order_exception_not_exist");
		}

		return productHrCombo;
	}

	@Override
	public OrderProductHrCombo getOrderDetailByOrderNo4Pay(String orderNo) {
		OrderProductHrCombo productHrCombo = getOrderDetailByOrderNo(orderNo);

		if (ObjectUtils.nullSafeEquals(productHrCombo.getOrderStatus(), HashRateOrderEnums.Status.noneffective.getCode())) {
			log.error("获取订单<orderNo:{}>支付信息失败:此订单支付已取消", orderNo);
			throw new CommonException("获取支付信息失败，此订单支付已取消", "order_pay_info_exception_status_cancel");
		}

		if (ObjectUtils.nullSafeEquals(productHrCombo.getOrderStatus(), HashRateOrderEnums.Status.payed.getCode())
				|| ObjectUtils.nullSafeEquals(productHrCombo.getOrderStatus(), HashRateOrderEnums.Status.payed_effective.getCode())) {
			log.error("获取订单<orderNo:{}>支付信息失败:此订单已支付", orderNo);
			throw new CommonException("获取支付信息失败，此订单已支付", "order_pay_info_exception_status_payed");
		}

		if (orderUtils.isOvertime(productHrCombo.getCreateTime())) {
			throw new CommonException("支付超时,该订单已取消", "order_exception_over_time");
		}
		return productHrCombo;
	}

	@Override
	public BaseOrderRep getOrderPayInfo(String orderNo) {
		OrderProductHrCombo productHrCombo = getOrderDetailByOrderNo4Pay(orderNo);
		List<ProductPayTypeRep> productPayTypeList = productPayTypeService.listValidPayTypeByOrderType(productHrCombo.getOrderMoney(), sessionUtil.getUser().getUserId(), productHrCombo.getOrderType());
		if (ObjectUtils.isEmpty(productPayTypeList)) {
			throw new CommonException("会员余额不足", "store_balance_not_enough");
		}
		return BaseOrderRep.buildProductHrCombo(productHrCombo, orderUtils.getOvertime(productHrCombo.getCreateTime()), productPayTypeList);
	}


	@Override
	@Transactional(rollbackFor = Exception.class)
	public void cancelOrder(String orderNo) {
		OrderProductHrCombo orderProductHrCombo = getOne(new QueryWrapper<OrderProductHrCombo>().lambda().eq(OrderProductHrCombo::getHrOrderNo, orderNo));
		if (ObjectUtils.isEmpty(orderProductHrCombo)) {
			throw new CommonException("取消失败，没有找到订单", "cancel_order_fail_by_empty_order");
		}
		cancelOrder(orderProductHrCombo.getId());
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void cancelOrder(Integer orderId) {
		OrderProductHrCombo hrCombo = new OrderProductHrCombo();
		hrCombo.setId(orderId);
		hrCombo.setOrderStatus(HashRateOrderEnums.Status.noneffective.getCode());
		updateById(hrCombo);
		addProductOtherStockNum(orderId);
	}

	@Override
	public Integer totalEffectiveOrderByMemberIdAndComboId(Integer memberId, Integer comboId) {
		return baseMapper.totalEffectiveOrderByMemberIdAndComboId(memberId, HashRateOrderEnums.getHrComboTotalStatus(), comboId);
	}

	@Override
	public BigDecimal totalEffectiveOrderByMemberId(Integer memberId, Integer coinsId, Integer orderStatus) {
		return baseMapper.totalEffectiveOrderByMemberId(memberId, coinsId, orderStatus);
	}


	@Override
	public BigDecimal totalEffectiveHrRateLargeThanZeroByMemberId(Integer memberId) {
		return baseMapper.totalEffectiveHrRateLargeThanZeroByMemberId(memberId, HashRateOrderEnums.getHrComboUsingStatus());
	}

	@Override
	public BigDecimal totalEffectiveOrderByMemberList(List<Integer> memberIds) {
		List<Integer> orderStatus = HashRateOrderEnums.getHrComboUsingStatus();
		List<Integer> orderSource = HashRateOrderEnums.listEffectiveOrderSource();
		return baseMapper.totalEffectiveOrderMoneyByMemberIdsAndStatusAndSourceList(memberIds, orderStatus, orderSource);
	}

	@Override
	public BigDecimal totalEffectiveOrderAndStatusByMemberId(Integer memberId) {
		BigDecimal totalBashHR = baseMapper.totalEffectiveHrRateByMemberId(memberId, HashRateOrderEnums.getHrComboTotalStatus(), HashRateOrderEnums.listEffectiveOrderSource(), null);
		return totalBashHR;
	}

	private void addProductOtherStockNum(Integer orderId) {
		List<OrderProductHrComboDetails> detailsList = orderDetailsService.list(new QueryWrapper<OrderProductHrComboDetails>().lambda().eq(OrderProductHrComboDetails::getHrOrderId, orderId));
		detailsList.forEach(item -> {
			productHrComboService.updateProductStockNum(item.getComboId(), item.getOrderNum() * -1);
		});
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void renewOrder(String orderNo, RenewOrderReq req) {
		LoginUserSession loginUserSession = sessionUtil.getUser();
		if (loginUserSession.getStoreFreezeStatus() == com.service.dao.enums.MemberEnums.StoreStatus.FROZEN.getCode()) {
			throw new CommonException("账户资产已冻结，如有疑问请联系客服", "account_assets_frozen");
		}
		memberService.validSafetyPwd(loginUserSession.getUserId(), req.getSafetyPwd());
		//获取订单信息
		OrderProductHrCombo orderProductHrCombo = getOne(new QueryWrapper<OrderProductHrCombo>().lambda().eq(OrderProductHrCombo::getHrOrderNo, orderNo));
		if (ObjectUtils.isEmpty(orderProductHrCombo)) {
			throw new CommonException("不存在此订单", "order_exception_not_exist");
		}
		OrderProductHrComboDetails hrComboDetails = orderDetailsService.getOne(new QueryWrapper<OrderProductHrComboDetails>().lambda()
				.eq(OrderProductHrComboDetails::getHrOrderId, orderProductHrCombo.getId()).last(" limit 1"));
		if (!ObjectUtils.isEmpty(hrComboDetails)) {
			//判断订单是否结束并且结束时间小于等于限制天数
			SysConfig limitConfig = configService.getByName("ORDER_RENEW_LIMIT_DAYS");
			Date limitDate = DateUtil.nextCurrentDays(hrComboDetails.getEndTime(), Integer.parseInt(limitConfig.getConfValue()));
			Date current = new Date();
			if (current.before(hrComboDetails.getEndTime())) {
				throw new CommonException("当前订单还未结束，无法发起续约", "before_renew_limit_time");
			} else if (current.after(limitDate)) {
				throw new CommonException("已过续约天数限制，无法发起续约", "after_renew_limit_time");
			}
			//计算FIL消耗数量=质押币+gas数量
			BigDecimal needPledgeNum = hrComboDetails.getPledgeNum();
			BigDecimal needGasNum = hrComboDetails.getGasNum();
			//获取USDT消耗数量
			BigDecimal needUSDTNum = hrComboDetails.getUsdtNum();
			MemberStore memberFILStore = memberStoreService.getMemberStore(loginUserSession.getUserId(), CoinsEnum.FIL.getName());
			boolean isLockFIL = memberStoreLockUtils.lock(loginUserSession.getUserId(), CoinsEnum.FIL.getCode());
			if (!isLockFIL) {
				log.info("账户{}已被锁定", loginUserSession.getUserId());
				return;
			}
			if (memberFILStore.getNum().compareTo(needPledgeNum) < 0) {
				throw new CommonException("会员余额不足,无法续约", "store_balance_not_enough");
			}
			memberStoreService.changeMemberStore(
					MemberStoreChange.builder()
							.memberId(loginUserSession.getUserId())
							.coinsId(CoinsEnum.FIL.getCode())
							.coinsName(CoinsEnum.FIL.getName())
							.jaType(MemberJAType.RENEW_FIL_PLEDGE)
							.orderId(orderProductHrCombo.getId())
							.custodyFee(BigDecimal.ZERO)
							.orderDetailId(hrComboDetails.getId())
							.changeNum(needPledgeNum)
							.remark(orderProductHrCombo.getMemberId() + MemberJAType.RENEW_FIL_PLEDGE.getMsg().toString())
							.build());
			memberStoreLockUtils.unlock(loginUserSession.getUserId(), CoinsEnum.FIL.getCode());

			MemberStore memberFILGasStore = memberStoreService.getMemberStore(loginUserSession.getUserId(), CoinsEnum.FIL.getName());
			boolean isLockFILGas = memberStoreLockUtils.lock(loginUserSession.getUserId(), CoinsEnum.FIL.getCode());
			if (!isLockFIL) {
				log.info("账户{}已被锁定", loginUserSession.getUserId());
				return;
			}
			if (memberFILGasStore.getNum().compareTo(needGasNum) < 0) {
				throw new CommonException("GAS不足,无法续约", "store_balance_not_enough");
			}
			memberStoreService.changeMemberStore(
					MemberStoreChange.builder()
							.memberId(loginUserSession.getUserId())
							.coinsId(CoinsEnum.FIL.getCode())
							.coinsName(CoinsEnum.FIL.getName())
							.jaType(MemberJAType.RENEW_FIL_GAS)
							.orderId(orderProductHrCombo.getId())
							.custodyFee(BigDecimal.ZERO)
							.orderDetailId(hrComboDetails.getId())
							.changeNum(needGasNum)
							.remark(orderProductHrCombo.getMemberId() + MemberJAType.RENEW_FIL_GAS.getMsg().toString())
							.build());
			memberStoreLockUtils.unlock(loginUserSession.getUserId(), CoinsEnum.FIL.getCode());

			MemberStore memberUSDTStore = memberStoreService.getMemberStore(loginUserSession.getUserId(), CoinsEnum.USDT.getName());
			boolean isLockUSDT = memberStoreLockUtils.lock(loginUserSession.getUserId(), CoinsEnum.USDT.getCode());
			if (!isLockUSDT) {
				log.info("账户{}已被锁定", loginUserSession.getUserId());
				return;
			}
			if (memberUSDTStore.getNum().compareTo(needUSDTNum) < 0) {
				throw new CommonException("会员余额不足", "store_balance_not_enough");
			}
			memberStoreService.changeMemberStore(
					MemberStoreChange.builder()
							.memberId(loginUserSession.getUserId())
							.coinsId(CoinsEnum.USDT.getCode())
							.coinsName(CoinsEnum.USDT.getName())
							.jaType(MemberJAType.RENEW_USDT_DEDUCTION)
							.orderId(orderProductHrCombo.getId())
							.custodyFee(BigDecimal.ZERO)
							.orderDetailId(hrComboDetails.getId())
							.changeNum(needUSDTNum)
							.remark(orderProductHrCombo.getMemberId() + MemberJAType.RENEW_USDT_DEDUCTION.getMsg().toString())
							.build());
			memberStoreLockUtils.unlock(loginUserSession.getUserId(), CoinsEnum.USDT.getCode());
			//更新订单状态和结束时间
			renewOrderAndDetails(orderProductHrCombo, hrComboDetails);
		}
	}

	@Override
	public MyHashRateTotalRep totalHashRate(String coinsName) {
		LoginUserSession session = sessionUtil.getUser();
		//获取用户购买算力总数
		BigDecimal totalBashHR = baseMapper.totalEffectiveHrRateByMemberId(session.getUserId(), HashRateOrderEnums.getHrComboUsingStatus(), HashRateOrderEnums.Type.base.getSourceList(), coinsName);
		//获取填充算力总数
		BigDecimal totalPaddingHR = orderProductHrComboPaddingService.totalEffectPaddingHashRate(coinsName, session.getUserId(), new Date());
		//获取全网算力
		String totalNetworkHR = null;
		Coins coins = coinService.getOne(new QueryWrapper<Coins>().lambda().eq(Coins::getCoinName, coinsName));
		BigDecimal outputNum = BigDecimal.ZERO;
		if (CoinsEnum.FIL.getName().equals(coins.getCoinName())) {
			SysQuotesIpfx ipfxConfig = JSONObject.parseObject(memCache.get(IPFSConstant.REDIS_IPFS_KEY), SysQuotesIpfx.class);
			if (ObjectUtils.isEmpty(ipfxConfig)) {
				LambdaQueryWrapper<SysQuotesIpfx> queryWrapper = new LambdaQueryWrapper<>();
				queryWrapper.orderByDesc(SysQuotesIpfx::getUpdateTime);
				queryWrapper.last("limit 1");
				ipfxConfig = sysQuotesIpfxService.getOne(queryWrapper);
			}
			outputNum = new BigDecimal(ipfxConfig.getPer_24h_rewards().replace(" FIL/TiB", ""));
			totalNetworkHR = ipfxConfig.getTotalHashRate();
		} else {
			outputNum = coins.getOutputNum();
		}
		BigDecimal availableBalance = BigDecimal.ZERO;
		MemberStore store = memberStoreService.getMemberStore(session.getUserId(), coinsName);
		if (ObjectUtils.isEmpty(store)) {
			availableBalance = store.getNum();
		}
		return MyHashRateTotalRep.builder()
				.outputNum(outputNum)
				.totalBashHR(totalBashHR)
				.totalPaddingHR(totalPaddingHR)
				.totalNetworkHR(totalNetworkHR)
				.availableBalance(availableBalance)
				.build();
	}

	@Override
	public TotalMyHashRateRep totalHashRateDetails(String coinsName) {
		LoginUserSession session = sessionUtil.getUser();
		//获取用户购买算力总数
		BigDecimal totalBashHR = baseMapper.totalEffectiveHrRateByMemberId(session.getUserId(), HashRateOrderEnums.getHrComboUsingStatus(), HashRateOrderEnums.Type.base.getSourceList(), coinsName);
		//获取填充算力总数
		BigDecimal totalPaddingHR = orderProductHrComboPaddingService.totalEffectPaddingHashRate(coinsName, session.getUserId(), new Date());
		OrderProductHrCombo orderProductHrCombo = baseMapper.getFirstEffectOrderByMemberIdAndCoinsName(session.getUserId(), coinsName, HashRateOrderEnums.getHrComboUsingStatus());
		Date current = new Date();
		Date yesterday = DateUtil.addDay(current, -1);
		Integer runDays = 0;
		if (!ObjectUtils.isEmpty(orderProductHrCombo)) {
			//根据第一个生效订单查询距离当前的时间差
			runDays = DateUtil.differentDays(orderProductHrCombo.getStartTime(), current);
		}
		BigDecimal yesterdayIncome = memberJAService.getSomedayTotalStatement(session.getUserId(), coinsName, yesterday, MemberJAType.getMiningOutPutType());
		BigDecimal totalIncome = memberJAService.getSomedayTotalStatement(session.getUserId(), coinsName, null, MemberJAType.getMiningOutPutType());
		Coins coins = coinService.getByCoinsName(coinsName);
		BigDecimal releasedNum = miningOrderService.totalMiningFrostNum(session.getUserId(), coins.getId(), null, null);
		BigDecimal unReleasedNum = miningOrderService.totalWaitReleaseNum(session.getUserId(), coins.getId());
		BigDecimal outputNum = BigDecimal.ZERO;
		if (CoinsEnum.FIL.getName().equals(coins.getCoinName())) {
			SysQuotesIpfx ipfxConfig = JSONObject.parseObject(memCache.get(IPFSConstant.REDIS_IPFS_KEY), SysQuotesIpfx.class);
			if (ObjectUtils.isEmpty(ipfxConfig)) {
				LambdaQueryWrapper<SysQuotesIpfx> queryWrapper = new LambdaQueryWrapper<>();
				queryWrapper.orderByDesc(SysQuotesIpfx::getUpdateTime);
				queryWrapper.last("limit 1");
				ipfxConfig = sysQuotesIpfxService.getOne(queryWrapper);
			}
			outputNum = new BigDecimal(ipfxConfig.getPer_24h_rewards().replace(" FIL/TiB", ""));
		} else {
			outputNum = coins.getOutputNum();
		}
		return TotalMyHashRateRep.builder()
				.totalHashRate(totalBashHR)
				.totalPaddingHashRate(totalPaddingHR)
				.runDays(runDays)
				.yesterdayIncome(yesterdayIncome)
				.totalIncome(totalIncome)
				.releasedNum(releasedNum)
				.unReleasedNum(unReleasedNum)
				.incomePerT(outputNum)
				.build();
	}

	@Override
	public MyOrderHashRateRep totalMyOrderHashRateByCoin(String coinsName) {
		LoginUserSession session = sessionUtil.getUser();
		MyOrderHashRateRep rep = new MyOrderHashRateRep();
		Coins coins = coinService.getByCoinsName(coinsName);
		if (CoinsEnum.FIL.getName().equals(coins.getCoinName())) {
			//统计当前用户的已释放数量
			rep.setAlreadyReleaseFILNum(memberJAService.getSomedayTotalStatement(session.getUserId(), coinsName, null, MemberJAType.getReleaseType()));
			//统计当前用户的待释放数量
			rep.setWaitReleaseFILNum(miningOrderService.totalWaitReleaseNum(session.getUserId(), coins.getId()));
			//获取单T收益
			SysQuotesIpfx ipfxConfig = JSONObject.parseObject(memCache.get(IPFSConstant.REDIS_IPFS_KEY), SysQuotesIpfx.class);
			if (ObjectUtils.isEmpty(ipfxConfig)) {
				LambdaQueryWrapper<SysQuotesIpfx> queryWrapper = new LambdaQueryWrapper<>();
				queryWrapper.orderByDesc(SysQuotesIpfx::getUpdateTime);
				queryWrapper.last("limit 1");
				ipfxConfig = sysQuotesIpfxService.getOne(queryWrapper);
			}
			BigDecimal outputNum = new BigDecimal(ipfxConfig.getPer_24h_rewards().replace(" FIL/TiB", ""));
			rep.setSingleTIncome(outputNum.multiply(new BigDecimal(0.8)));
		} else if (CoinsEnum.ETH.getName().equals(coins.getCoinName())) {
			rep.setSingleMIncome(coins.getOutputCurNum());
			rep.setTotalIncomeETHNum(memberJAService.getSomedayTotalStatement(session.getUserId(), coinsName, null, MemberJAType.getMiningIncomeType()));
		} else if (CoinsEnum.BTC.getName().equals(coins.getCoinName())) {
			rep.setSingleTIncome(coins.getOutputCurNum());
			rep.setTotalIncomeBTCNum(memberJAService.getSomedayTotalStatement(session.getUserId(), coinsName, null, MemberJAType.getMiningIncomeType()));
		}
		return rep;
	}

	/**
	 * @param memberIds
	 * @param orderStatus
	 * @Description: 统计用户们销量
	 * @Author: ty
	 * @Date: 2021/4/30 15:25
	 * @param: [memberIds]
	 * @return: java.math.BigDecimal
	 */
	@Override
	public BigDecimal totalEffectiveOrderPayByMemberList(List<Integer> memberIds, List<Integer> orderStatus) {
		return baseMapper.totalEffectiveOrderPayByMemberList(memberIds, orderStatus);
	}

	/**
	 * @param coinsName
	 * @param currentMonth
	 * @param limitNum
	 * @Description: 统计本月排行
	 * @Author: ty
	 * @Date: 2021/5/6 15:19
	 * @param: [coinsName, currentMonth, limitNum]
	 * @return: java.util.List<com.service.dao.dto.MemberRankRep>
	 */
	@Override
	public OrderMemberRank totalRankByPayMoneyAndSomeMonth(String coinsName, Date currentMonth) {
		//统计当月奖励池总量
		OrderMemberRank rep = new OrderMemberRank();
		String monthPattern = "yyyy-MM";
		String currentMonthStr = DateFormatUtils.format(currentMonth, monthPattern);
		RankMiningPoolRecord currentRankMiningPoolRecord = rankMiningPoolRecordService.getSomeMonthRecord(currentMonthStr);
		if (!ObjectUtils.isEmpty(currentRankMiningPoolRecord)) {
			rep.setRewardPool(currentRankMiningPoolRecord.getCurrentMonthPoolNum());
		} else {
			rep.setRewardPool(BigDecimal.ZERO);
		}
		//获取用户是代理商和分公司的用户
		List<Member> memberList = memberService.getMemberIdsByGradeList(GradeEnum.getProxAndComGrade());
		List<MemberRank> rankList = new ArrayList<>();
		if (!ObjectUtils.isEmpty(memberList)) {
			//统计伞下月新增T数
//			memberList.stream().forEach(item -> {
//				List<Integer> effectMemberIds = new ArrayList<>();
//				effectMemberIds.add(item.getId());
//				//获取用户伞下团队
//				List<Member> umbrellaMemberList = memberService.selectByPathAndStatus(item.getId());
//				if (!ObjectUtils.isEmpty(umbrellaMemberList)) {
//					for (Member umbrella : umbrellaMemberList) {
//						if (umbrella.getVipGrade() != item.getVipGrade()) {
//							effectMemberIds.add(umbrella.getId());
//						} else if (umbrella.getVipGrade() == item.getVipGrade()) {
//							break;
//						}
//					}
//					BigDecimal totalMemberHashRate = baseMapper.totalEffectiveHashRateByMemberIdsAndStatus(effectMemberIds, HashRateOrderEnums.getHrComboUsingStatus(), currentMonthStr);
//					if(totalMemberHashRate.compareTo(BigDecimal.ZERO) == 0){
//						return;
//					}
//					MemberRank memberRank = new MemberRank();
//					memberRank.setMemberAccount(item.getUserAccount().replaceAll("(\\d{3})\\d{6}(\\d{2})", "$1****$2"));
//					List<Member> inviteMembers = memberService.selectByPathAndStatus(item.getId());
//					memberRank.setInviteMemberNum(inviteMembers.size());
//					memberRank.setTotalTeamHashRate(totalMemberHashRate);
//					rankList.add(memberRank);
//				}
//			});
			for (Member item : memberList) {
				List<Integer> effectMemberIds = new ArrayList<>();
				effectMemberIds.add(item.getId());
				//获取用户伞下团队
				List<Member> umbrellaMemberList = memberService.selectByPathAndStatus(item.getId());
				if (!ObjectUtils.isEmpty(umbrellaMemberList)) {
					for (Member umbrella : umbrellaMemberList) {
						if (umbrella.getVipGrade() != item.getVipGrade()) {
							effectMemberIds.add(umbrella.getId());
						} else if (umbrella.getVipGrade() == item.getVipGrade()) {
							break;
						}
					}
				}
				BigDecimal totalMemberHashRate = baseMapper.totalEffectiveHashRateByMemberIdsAndStatus(effectMemberIds, HashRateOrderEnums.getHrComboUsingStatus(), currentMonthStr);
				if (totalMemberHashRate.compareTo(BigDecimal.ZERO) == 0) {
					continue;
				}
				MemberRank memberRank = new MemberRank();
				memberRank.setMemberAccount(item.getUserAccount().replaceAll("(\\d{3})\\d{6}(\\d{2})", "$1****$2"));
				List<Member> inviteMembers = memberService.selectByPathAndStatus(item.getId());
				memberRank.setInviteMemberNum(inviteMembers.size());
				memberRank.setTotalTeamHashRate(totalMemberHashRate);
				rankList.add(memberRank);
			}
		}
		if (!ObjectUtils.isEmpty(rankList)) {
			//根据团队有效算力排序
			Collections.sort(rankList, new Comparator<MemberRank>() {
				public int compare(MemberRank o1, MemberRank o2) {
					return o2.getTotalTeamHashRate().compareTo(o1.getTotalTeamHashRate());
				}
			});
			//排行序号添加
			for (int i = 0; i < rankList.size(); i++) {
				MemberRank memberRank = rankList.get(i);
				memberRank.setRankNo(i + 1);
			}
		}
		rep.setMemberRankRepList(rankList);
		return rep;
	}

	/**
	 * @param memberId
	 * @param coinsName
	 * @Description: 统计当前用户币种的质押数量
	 * @Author: ty
	 * @Date: 2021/5/11 15:17
	 * @param: [memberId, coinsName]
	 * @return: java.math.BigDecimal
	 */
	@Override
	public BigDecimal totalPledgeNumByMemberIdAndCoins(Integer memberId, String coinsName) {
		return orderDetailsService.totalPledgeNumByMemberIdAndCoins(memberId, coinsName);
	}

	/**
	 * 根据状态统计用户伞下算力
	 *
	 * @param memberIds
	 * @param orderStatus
	 * @return
	 */
	@Override
	public BigDecimal totalUmbrellaEffectiveHashRateByMemberIdsAndStatus(List<Integer> memberIds, List<Integer> orderStatus) {
		return baseMapper.totalUmbrellaEffectiveHashRateByMemberIdsAndStatus(memberIds,orderStatus);
	}

	private void renewOrderAndDetails(OrderProductHrCombo orderProductHrCombo, OrderProductHrComboDetails hrComboDetails) {
		Date current = new Date();
		//更新订单
		orderProductHrCombo.setStartTime(DateUtil.changeDateTo3point(new Date()));
		orderProductHrCombo.setEndTime(DateUtil.changeDateTo3point(DateUtils.addDays(current, hrComboDetails.getRenewalDays())));
		orderProductHrCombo.setOrderStatus(OrderProductOtherStatus.DELIVERED.getCode());
		orderProductHrCombo.setCreateTime(new Date());
		baseMapper.updateById(orderProductHrCombo);
		//更新订单详情
		hrComboDetails.setStartTime(DateUtil.changeDateTo3point(new Date()));
		hrComboDetails.setEndTime(DateUtil.changeDateTo3point(DateUtils.addDays(current, hrComboDetails.getRenewalDays())));
		hrComboDetails.setRenewalDays(hrComboDetails.getRenewalDays());
		hrComboDetails.setCreateTime(new Date());
		hrComboDetails.setRenewTime(new Date());
		orderDetailsService.updateById(hrComboDetails);
	}
}
